package com.zenithmind.document.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.result.Result;
import com.zenithmind.document.pojo.dto.DocumentVersionCreateDTO;
import com.zenithmind.document.pojo.dto.DocumentVersionUpdateDTO;
import com.zenithmind.document.pojo.query.DocumentVersionQueryDTO;
import com.zenithmind.document.pojo.vo.DocumentVersionVO;
import com.zenithmind.document.service.DocumentVersionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;

/**
 * 文档版本控制器
 * 遵循单一职责原则：专注于文档版本相关的HTTP接口
 * 遵循依赖倒置原则：依赖抽象服务接口
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@RestController
@RequestMapping("/api/document/version")
@RequiredArgsConstructor
@Validated
@Tag(name = "文档版本管理", description = "文档版本相关接口")
public class DocumentVersionController {

    private final DocumentVersionService documentVersionService;

    @PostMapping
    @Operation(summary = "创建版本", description = "创建文档新版本")
    public Result<DocumentVersionVO> createVersion(@Valid @RequestBody DocumentVersionCreateDTO createDTO) {
        log.info("创建文档版本请求: documentId={}", createDTO.getDocumentId());
        
        DocumentVersionVO result = documentVersionService.createVersion(createDTO);
        
        return Result.success(result);
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新版本", description = "更新文档版本信息")
    public Result<Boolean> updateVersion(
            @Parameter(description = "版本ID", required = true) @PathVariable @NotBlank String id,
            @Valid @RequestBody DocumentVersionUpdateDTO updateDTO) {
        
        log.info("更新文档版本请求: id={}", id);
        
        Boolean result = documentVersionService.updateVersion(id, updateDTO);
        
        return Result.success(result);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除版本", description = "删除文档版本")
    public Result<Boolean> deleteVersion(
            @Parameter(description = "版本ID", required = true) @PathVariable @NotBlank String id) {
        
        log.info("删除文档版本请求: id={}", id);
        
        Boolean result = documentVersionService.deleteVersion(id);
        
        return Result.success(result);
    }

    @DeleteMapping("/batch")
    @Operation(summary = "批量删除版本", description = "批量删除文档版本")
    public Result<Boolean> batchDeleteVersions(
            @Parameter(description = "版本ID列表", required = true) @RequestBody @NotEmpty List<String> ids) {
        
        log.info("批量删除文档版本请求: ids={}", ids);
        
        Boolean result = documentVersionService.batchDeleteVersions(ids);
        
        return Result.success(result);
    }

    @GetMapping("/page")
    @Operation(summary = "分页查询版本", description = "分页查询文档版本列表")
    public Result<IPage<DocumentVersionVO>> getVersionPage(@Valid DocumentVersionQueryDTO queryDTO) {
        log.info("分页查询文档版本请求");
        
        IPage<DocumentVersionVO> result = documentVersionService.getVersionPage(queryDTO);
        
        return Result.success(result);
    }

    @GetMapping("/{id}")
    @Operation(summary = "获取版本详情", description = "获取文档版本详细信息")
    public Result<DocumentVersionVO> getVersionDetail(
            @Parameter(description = "版本ID", required = true) @PathVariable @NotBlank String id) {
        
        log.info("获取版本详情请求: id={}", id);
        
        DocumentVersionVO result = documentVersionService.getVersionDetail(id);
        
        return Result.success(result);
    }

    @GetMapping("/document/{documentId}")
    @Operation(summary = "获取文档版本列表", description = "获取指定文档的版本列表")
    public Result<List<DocumentVersionVO>> getDocumentVersions(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "是否包含已删除版本") @RequestParam(required = false, defaultValue = "false") Boolean includeDeleted) {
        
        log.info("获取文档版本列表请求: documentId={}", documentId);
        
        List<DocumentVersionVO> result = documentVersionService.getDocumentVersions(documentId, includeDeleted);
        
        return Result.success(result);
    }

    @GetMapping("/document/{documentId}/current")
    @Operation(summary = "获取当前版本", description = "获取文档的当前版本")
    public Result<DocumentVersionVO> getCurrentVersion(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId) {
        
        log.info("获取当前版本请求: documentId={}", documentId);
        
        DocumentVersionVO result = documentVersionService.getCurrentVersion(documentId);
        
        return Result.success(result);
    }

    @GetMapping("/document/{documentId}/history")
    @Operation(summary = "获取版本历史", description = "获取文档的版本历史")
    public Result<List<DocumentVersionVO>> getVersionHistory(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取版本历史请求: documentId={}", documentId);
        
        List<DocumentVersionVO> result = documentVersionService.getVersionHistory(documentId, limit);
        
        return Result.success(result);
    }

    @PostMapping("/{versionId}/restore")
    @Operation(summary = "恢复版本", description = "恢复到指定版本")
    public Result<DocumentVersionVO> restoreVersion(
            @Parameter(description = "版本ID", required = true) @PathVariable @NotBlank String versionId) {
        
        log.info("恢复版本请求: versionId={}", versionId);

        try {
            String userId = UserContext.getUserId();

            // 首先获取版本详情以获取文档ID
            DocumentVersionVO versionDetail = documentVersionService.getVersionDetail(versionId);
            if (versionDetail == null) {
                return Result.fail("版本不存在");
            }

            DocumentVersionVO result = documentVersionService.restoreVersion(
                versionDetail.getDocumentId(), versionId, userId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("恢复版本失败: versionId={}", versionId, e);
            return Result.fail("恢复版本失败: " + e.getMessage());
        }
    }

    @PostMapping("/document/{documentId}/create-from-current")
    @Operation(summary = "从当前版本创建新版本", description = "基于当前版本创建新版本")
    public Result<DocumentVersionVO> createVersionFromCurrent(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "版本描述", required = true) @RequestParam @NotBlank String description) {
        
        log.info("从当前版本创建新版本请求: documentId={}", documentId);

        try {
            String userId = UserContext.getUserId();

            // 创建版本DTO
            DocumentVersionCreateDTO createDTO = new DocumentVersionCreateDTO();
            createDTO.setDocumentId(documentId);
            createDTO.setDescription(description);
            createDTO.setCreatorId(userId);

            DocumentVersionVO result = documentVersionService.createVersion(createDTO);
            return Result.success(result);
        } catch (Exception e) {
            log.error("从当前版本创建新版本失败: documentId={}", documentId, e);
            return Result.fail("创建版本失败: " + e.getMessage());
        }
    }

    @PostMapping("/compare")
    @Operation(summary = "比较版本", description = "比较两个版本")
    public Result<Object> compareVersions(
            @Parameter(description = "版本1 ID", required = true) @RequestParam @NotBlank String version1Id,
            @Parameter(description = "版本2 ID", required = true) @RequestParam @NotBlank String version2Id) {
        
        log.info("比较版本请求: version1Id={}, version2Id={}", version1Id, version2Id);

        try {
            Object result = documentVersionService.compareVersions(version1Id, version2Id);
            return Result.success(result);
        } catch (Exception e) {
            log.error("比较版本失败: version1Id={}, version2Id={}", version1Id, version2Id, e);
            return Result.fail("比较版本失败: " + e.getMessage());
        }
    }

    @GetMapping("/document/{documentId}/between")
    @Operation(summary = "获取版本范围", description = "获取指定版本范围内的版本列表")
    public Result<List<DocumentVersionVO>> getVersionsBetween(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "起始版本号", required = true) @RequestParam @NotBlank String startVersion,
            @Parameter(description = "结束版本号", required = true) @RequestParam @NotBlank String endVersion) {
        
        log.info("获取版本范围请求: documentId={}, startVersion={}, endVersion={}", documentId, startVersion, endVersion);

        try {
            // 获取文档的所有版本，然后过滤范围
            List<DocumentVersionVO> allVersions = documentVersionService.getDocumentVersions(documentId, false);

            List<DocumentVersionVO> result = allVersions.stream()
                .filter(version -> {
                    String versionNumber = version.getVersionNumber();
                    return isVersionInRange(versionNumber, startVersion, endVersion);
                })
                .collect(java.util.stream.Collectors.toList());

            return Result.success(result);
        } catch (Exception e) {
            log.error("获取版本范围失败: documentId={}, startVersion={}, endVersion={}",
                documentId, startVersion, endVersion, e);
            return Result.fail("获取版本范围失败: " + e.getMessage());
        }
    }

    @GetMapping("/document/{documentId}/version/{versionNumber}")
    @Operation(summary = "根据版本号获取版本", description = "根据版本号获取指定版本")
    public Result<DocumentVersionVO> getVersionByNumber(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "版本号", required = true) @PathVariable @NotBlank String versionNumber) {
        
        log.info("根据版本号获取版本请求: documentId={}, versionNumber={}", documentId, versionNumber);

        try {
            // 获取文档的所有版本，然后根据版本号查找
            List<DocumentVersionVO> versions = documentVersionService.getDocumentVersions(documentId, false);

            DocumentVersionVO result = versions.stream()
                .filter(version -> versionNumber.equals(version.getVersionNumber()))
                .findFirst()
                .orElse(null);

            if (result == null) {
                return Result.fail("版本不存在: " + versionNumber);
            }

            return Result.success(result);
        } catch (Exception e) {
            log.error("根据版本号获取版本失败: documentId={}, versionNumber={}", documentId, versionNumber, e);
            return Result.fail("获取版本失败: " + e.getMessage());
        }
    }

    @PostMapping("/merge")
    @Operation(summary = "合并版本", description = "合并两个版本")
    public Result<Boolean> mergeVersions(
            @Parameter(description = "目标版本ID", required = true) @RequestParam @NotBlank String targetVersionId,
            @Parameter(description = "源版本ID", required = true) @RequestParam @NotBlank String sourceVersionId) {
        
        log.info("合并版本请求: targetVersionId={}, sourceVersionId={}", targetVersionId, sourceVersionId);

        try {
            String userId = UserContext.getUserId();

            // 获取源版本和目标版本的详情
            DocumentVersionVO sourceVersion = documentVersionService.getVersionDetail(sourceVersionId);
            DocumentVersionVO targetVersion = documentVersionService.getVersionDetail(targetVersionId);

            if (sourceVersion == null || targetVersion == null) {
                return Result.fail("版本不存在");
            }

            // 模拟合并逻辑：创建一个新版本包含合并后的内容
            DocumentVersionCreateDTO createDTO = new DocumentVersionCreateDTO();
            createDTO.setDocumentId(targetVersion.getDocumentId());
            createDTO.setDescription("合并版本: " + sourceVersion.getVersionNumber() + " -> " + targetVersion.getVersionNumber());
            createDTO.setCreatorId(userId);

            DocumentVersionVO mergedVersion = documentVersionService.createVersion(createDTO);
            Boolean result = mergedVersion != null;

            return Result.success(result);
        } catch (Exception e) {
            log.error("合并版本失败: targetVersionId={}, sourceVersionId={}", targetVersionId, sourceVersionId, e);
            return Result.fail("合并版本失败: " + e.getMessage());
        }
    }

    @PostMapping("/{sourceVersionId}/copy")
    @Operation(summary = "复制版本", description = "复制版本到其他文档")
    public Result<DocumentVersionVO> copyVersion(
            @Parameter(description = "源版本ID", required = true) @PathVariable @NotBlank String sourceVersionId,
            @Parameter(description = "目标文档ID", required = true) @RequestParam @NotBlank String targetDocumentId) {
        
        log.info("复制版本请求: sourceVersionId={}, targetDocumentId={}", sourceVersionId, targetDocumentId);

        try {
            String userId = UserContext.getUserId();
            DocumentVersionVO result = documentVersionService.copyVersion(sourceVersionId, targetDocumentId, userId);
            return Result.success(result);
        } catch (Exception e) {
            log.error("复制版本失败: sourceVersionId={}, targetDocumentId={}", sourceVersionId, targetDocumentId, e);
            return Result.fail("复制版本失败: " + e.getMessage());
        }
    }

    @PostMapping("/document/{documentId}/cleanup")
    @Operation(summary = "清理旧版本", description = "清理文档的旧版本")
    public Result<Integer> cleanupOldVersions(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "保留版本数量") @RequestParam(required = false, defaultValue = "10") Integer keepCount) {
        
        log.info("清理旧版本请求: documentId={}, keepCount={}", documentId, keepCount);
        
        Integer result = documentVersionService.cleanupOldVersions(documentId, keepCount);
        
        return Result.success(result);
    }

    @GetMapping("/document/{documentId}/statistics")
    @Operation(summary = "获取版本统计", description = "获取文档版本统计信息")
    public Result<Object> getVersionStatistics(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId) {
        
        log.info("获取版本统计请求: documentId={}", documentId);
        
        Object result = documentVersionService.getVersionStatistics(documentId);
        
        return Result.success(result);
    }

    @GetMapping("/document/{documentId}/change-logs")
    @Operation(summary = "获取版本变更日志", description = "获取文档版本变更日志")
    public Result<List<Object>> getVersionChangeLogs(
            @Parameter(description = "文档ID", required = true) @PathVariable @NotBlank String documentId,
            @Parameter(description = "限制数量") @RequestParam(required = false, defaultValue = "20") Integer limit) {
        
        log.info("获取版本变更日志请求: documentId={}", documentId);

        try {
            // 获取版本历史作为变更日志
            List<DocumentVersionVO> versionHistory = documentVersionService.getVersionHistory(documentId, limit);

            // 转换为变更日志格式
            List<Object> result = versionHistory.stream()
                .map(version -> {
                    java.util.Map<String, Object> changeLog = new java.util.HashMap<>();
                    changeLog.put("versionId", version.getId());
                    changeLog.put("versionNumber", version.getVersionNumber());
                    changeLog.put("description", version.getDescription());
                    changeLog.put("creatorId", version.getCreatorId());
                    changeLog.put("createTime", version.getCreateTime());
                    changeLog.put("changeType", "VERSION_CREATED");
                    return changeLog;
                })
                .collect(java.util.stream.Collectors.toList());

            return Result.success(result);
        } catch (Exception e) {
            log.error("获取版本变更日志失败: documentId={}", documentId, e);
            return Result.fail("获取版本变更日志失败: " + e.getMessage());
        }
    }

    @GetMapping("/check-exists")
    @Operation(summary = "检查版本是否存在", description = "检查指定版本是否存在")
    public Result<Boolean> checkVersionExists(
            @Parameter(description = "文档ID", required = true) @RequestParam @NotBlank String documentId,
            @Parameter(description = "版本号", required = true) @RequestParam @NotBlank String versionNumber) {
        
        log.info("检查版本是否存在请求: documentId={}, versionNumber={}", documentId, versionNumber);

        try {
            Boolean result = documentVersionService.checkVersionNumberExists(documentId, versionNumber, null);
            return Result.success(result);
        } catch (Exception e) {
            log.error("检查版本是否存在失败: documentId={}, versionNumber={}", documentId, versionNumber, e);
            return Result.fail("检查版本失败: " + e.getMessage());
        }
    }

    /**
     * 检查版本号是否在指定范围内
     */
    private boolean isVersionInRange(String versionNumber, String startVersion, String endVersion) {
        if (versionNumber == null) {
            return false;
        }

        try {
            // 简单的版本号比较逻辑
            double version = parseVersionNumber(versionNumber);
            double start = parseVersionNumber(startVersion);
            double end = parseVersionNumber(endVersion);

            return version >= start && version <= end;
        } catch (Exception e) {
            log.warn("版本号解析失败: versionNumber={}, startVersion={}, endVersion={}",
                versionNumber, startVersion, endVersion);
            return false;
        }
    }

    /**
     * 解析版本号为数字
     */
    private double parseVersionNumber(String versionNumber) {
        if (versionNumber == null || versionNumber.trim().isEmpty()) {
            return 0.0;
        }

        try {
            // 处理类似 "1.0", "2.1" 的版本号
            String[] parts = versionNumber.split("\\.");
            if (parts.length >= 2) {
                int major = Integer.parseInt(parts[0]);
                int minor = Integer.parseInt(parts[1]);
                return major + (minor / 10.0);
            } else if (parts.length == 1) {
                return Double.parseDouble(parts[0]);
            }
        } catch (NumberFormatException e) {
            log.warn("版本号格式错误: {}", versionNumber);
        }

        return 0.0;
    }
}
